package com.gta.edu.sdk.base.dao.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.RowSet;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import com.gta.edu.sdk.base.dao.IBaseDao;
import com.gta.edu.sdk.common.cache.TableMapperCache;
import com.gta.edu.sdk.common.dto.EntityTableMapDto;
import com.gta.edu.sdk.common.dto.Page;
import com.gta.edu.sdk.common.dto.Sort;
import com.gta.edu.sdk.mybatis.common.BaseDao;
import com.gta.edu.sdk.mybatis.common.Entity;
import com.gta.edu.sdk.util.EntityTableReflectUtil;
import com.gta.edu.sdk.util.StringUtil;

/**
 * 通用数据访问实现
 * 
 * @author ya.feng
 *
 * @param <T>
 */
@Component("baseDao")
public class 	BaseDaoImpl<T extends Entity> extends BaseDao<T> implements IBaseDao<T> {
	private static final Logger LOG = LogManager.getLogger(BaseDaoImpl.class);
	public static final String SQL_SELECT = "select";
	public static final String SQL_FROM = "from";
	public static final String SQL_COUNT = "count(1)";
	public static final String ROWNUM_ALIAS = "rownum_";
	public static final String ROWNUM_NAME = "rownum";

	@Override
	public void save(Entity entity) {
		this.save("com.gta.edu.sdk.base.dao.mapper.BaseMapper.save", entity);
	}

	@Override
	public void update(Entity entity) {
		this.update("com.gta.edu.sdk.base.dao.mapper.BaseMapper.update", entity);
	}

	@Override
	public void saveOrUpdate(Entity entity) {
		this.update("com.gta.edu.sdk.base.dao.mapper.BaseMapper.saveOrUpdate", entity);
	}

	public int executeSql(String sql, Map<String, Object> params) {
		params.put("sql", sql);
//		LOG.info("sql:" + sql + ",params:" + );
		return this.update("com.gta.edu.sdk.base.dao.mapper.BaseMapper.executeSql", params);
	}

	@Override
	public void delete(Class<? extends Entity> cls, String id) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("cls", cls);
		params.put("id", id);
		this.delete("com.gta.edu.sdk.base.dao.mapper.BaseMapper.delete", params);
	}

	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<T> findAll(Class<T> cls, boolean isDefaultSort, Sort sort, boolean isDefaultDel) {
		EntityTableMapDto dto = TableMapperCache.getInstance().get(cls);
		StringBuilder sqlCount = new StringBuilder("select * from ");
		sqlCount.append(dto.getTableName());
		if (isDefaultDel) {
			sqlCount.append(" where DEL_SIGN=0 ");
		}
		boolean isSort = false;
		if (sort != null && !StringUtil.isNullOrEmpty(sort.getFields())) {
			isSort = true;
			sqlCount.append(" order by ");
			String[] fields = sort.getFields().split(",");
			String[] orders = sort.getOrders().split(",");
			for (int i = 0; i < fields.length - 1; i++) {
				sqlCount.append(dto.getFields().get(fields[i])).append(' ').append(orders[i]).append(',');
			}
			sqlCount.append(dto.getFields().get(fields[fields.length - 1])).append(' ')
					.append(orders[orders.length - 1]);
		}
		if (!isSort && isDefaultSort) {
			sqlCount.append(" order by UPDATE_TIME desc");
		}
		try {
			RowSet rs = this.queryset(sqlCount.toString());
			if (rs != null) {
				List result = new ArrayList();
				while (rs.next()) {
					result.add(EntityTableReflectUtil.getObject(cls, rs));
				}
				return result;
			} else {
				LOG.error("数据库查询为空！");
			}
		} catch (Exception e) {
			LOG.error("查询实体类【" + cls + "】所有的记录出现了异常", e);
		}
		return null;
	}

	/**
	 * @description 根据sql语句查询记录
	 * @author fengya
	 * @date 2017年6月27日 上午11:26:50
	 * @param cls
	 *            查询结果生成的对象类型
	 * @param sqlContext
	 *            执行的sql语句
	 * @param sort
	 *            对查询结果的字段进行排序列表
	 * @param isDefaultSort
	 *            是否支持默认排序，默认排序按照order by UPDATE_TIME desc进行
	 * @param parameters
	 *            查询参数
	 * @return
	 * @return List<E> 查询的结果集对象集合
	 */
	public <E> List<E> findAllBySQL(Class<E> cls, final String sqlContext, final Sort sort, boolean isDefaultSort,
			final Object... parameters) {
		StringBuilder sqlLower = new StringBuilder(sqlContext);
		boolean isSort = false;
		if (sort != null && !StringUtil.isNullOrEmpty(sort.getFields())) {
			isSort = true;
			sqlLower.append(" order by ");
			String[] fields = sort.getFields().split(",");
			String[] orders = sort.getOrders().split(",");
			for (int i = 0; i < fields.length - 1; i++) {
				sqlLower.append(" ").append(EntityTableReflectUtil.classNameToTable(fields[i])).append(" ")
						.append(orders[i]).append(',');
			}
			sqlLower.append(" ").append(EntityTableReflectUtil.classNameToTable(fields[fields.length - 1])).append(" ")
					.append(orders[orders.length - 1]);
		}
		if (!isSort && isDefaultSort) {
			sqlLower.append(" order by UPDATE_TIME desc");
		}
		try {
			RowSet rs = this.queryset(sqlLower.toString(), parameters);
			if (rs != null) {
				List<E> result = new ArrayList<E>();
				while (rs.next()) {
					result.add(EntityTableReflectUtil.getObject(cls, rs));
				}
				return result;
			}
		} catch (Exception e) {
			LOG.error("查询实体类【" + cls + "】所有的记录出现了异常,查询sql:" + sqlLower.toString(), e);
		}
		return null;
	}

	@Override
	public <E> E get(Class<E> cls, String id) {
		try {
			EntityTableMapDto dto = TableMapperCache.getInstance().get(cls);
			StringBuilder sql = new StringBuilder();
			sql.append("select * from ").append(dto.getTableName()).append(" where id=?");
			RowSet rs = this.queryset(sql.toString(), id);
			if (rs.next()) {
				return EntityTableReflectUtil.getObject(cls, rs);
			}
		} catch (Exception e) {
			LOG.error("根据ID查询实体对象出现了异常", e);
		}
		return null;
	}

	/**
	 * @description 唯一性查询对象，适合做唯一性约束的字段查询，查询结果必须只有一条记录或者无记录
	 * @author fengya
	 * @date 2017年6月27日 上午11:55:13
	 * @param cls
	 *            查询结果对象类型
	 * @param sqlContext
	 *            查询sql语句
	 * @param parameters
	 *            查询参数
	 * @return
	 * @return E 查询结果对象
	 */
	public <E> E findUnique(Class<E> cls, final String sqlContext, final Object... parameters) {
		try {
			RowSet rs = this.queryset(sqlContext, parameters);
			E result = null;
			int count = 0;
			while (rs.next()) {
				if (count > 0) {
					throw new SQLException("唯一性查询结果出现了多条记录！");
				}
				result = EntityTableReflectUtil.getObject(cls, rs);
				count++;
			}
			return result;
		} catch (Exception e) {
			LOG.error("查询实体类【" + cls + "】所有的记录出现了异常,查询sql:" + sqlContext, e);
		}
		return null;
	}

//  mysql下的分页
//	@SuppressWarnings({ "rawtypes", "unchecked" })
//	@Override
//	public void findAsPage(Page<T> page, Sort sort, T t, boolean isDefaultSort) {
//		EntityTableMapDto dto = TableMapperCache.getInstance().get(t.getClass());
//		StringBuilder sqlCount = new StringBuilder("select count(1) from ");
//		sqlCount.append(dto.getTableName());
//		StringBuilder sql = null;
//		try {
//			Map<String, Object> whereValue = EntityTableReflectUtil.entitySQLWhere(t);
//			Object[] params = null;
//			if (whereValue.size() > 0) {
//				sqlCount.append(" where ");
//				StringBuilder whereStr = new StringBuilder();
//				params = new Object[whereValue.size()];
//				Entry<String, Object> entry = null;
//				Iterator<Entry<String, Object>> entryIt = whereValue.entrySet().iterator();
//				int i = 0;
//				while (entryIt.hasNext()) {
//					entry = entryIt.next();
//					whereStr.append(entry.getKey()).append("=? and ");
//					params[i++] = entry.getValue();
//				}
//				sqlCount.append(whereStr.substring(0, whereStr.length() - 4));
//
//			}
//			RowSet rs = this.queryset(sqlCount.toString(), params);
//			if (rs.next()) {
//				page.setTotalCount(rs.getInt(1));
//				sql = new StringBuilder(sqlCount.toString().replace(SQL_COUNT, "*"));
//				boolean isSort = false;
//				if (!StringUtil.isNullOrEmpty(sort.getFields())) {
//					isSort = true;
//					sql.append(" order by ");
//					String[] fields = sort.getFields().split(",");
//					String[] orders = sort.getOrders().split(",");
//					for (int i = 0; i < fields.length - 1; i++) {
//						sql.append(dto.getFields().get(fields[i])).append(' ').append(orders[i]).append(',');
//					}
//					sql.append(dto.getFields().get(fields[fields.length - 1])).append(' ')
//							.append(orders[orders.length - 1]);
//				}
//				if (isDefaultSort && !isSort) {
//					sql.append(" order by UPDATE_TIME desc ");
//				}
//				sql.append(" limit ").append(page.getOffset()).append(",").append(page.getPageSize());
//				rs = this.queryset(sql.toString(), params);
//				List result = new ArrayList();
//				while (rs.next()) {
//					result.add(EntityTableReflectUtil.getObject(t.getClass(), rs));
//				}
//				page.setResult(result);
//			}
//		} catch (Exception e) {
//			LOG.error("分页查询出现了异常,查询语句：" + sql.toString(), e);
//		}
//	}
	
//  oracle下的分页
//	@SuppressWarnings({ "rawtypes", "unchecked" })
//	@Override
//	public void findAsPage(Page<T> page, Sort sort, T t, boolean isDefaultSort) {
//		EntityTableMapDto dto = TableMapperCache.getInstance().get(t.getClass());
//		StringBuilder sqlCount = new StringBuilder("select count(1) from ");
//		sqlCount.append(dto.getTableName());
//		StringBuilder sql = null;
//		try {
//			Map<String, Object> whereValue = EntityTableReflectUtil.entitySQLWhere(t);
//			Object[] params = null;
//			if (whereValue.size() > 0) {
//				sqlCount.append(" where ");
//				StringBuilder whereStr = new StringBuilder();
//				params = new Object[whereValue.size()];
//				Entry<String, Object> entry = null;
//				Iterator<Entry<String, Object>> entryIt = whereValue.entrySet().iterator();
//				int i = 0;
//				while (entryIt.hasNext()) {
//					entry = entryIt.next();
//					whereStr.append(entry.getKey()).append("=? and ");
//					params[i++] = entry.getValue();
//				}
//				sqlCount.append(whereStr.substring(0, whereStr.length() - 4));
//
//			}
//			RowSet rs = this.queryset(sqlCount.toString(), params);
//			if (rs.next()) {
//				page.setTotalCount(rs.getInt(1));
//				sql = new StringBuilder(sqlCount.toString().replace(SQL_COUNT, "*"));
//				boolean isSort = false;
//				if (!StringUtil.isNullOrEmpty(sort.getFields())) {
//					isSort = true;
//					sql.append(" order by ");
//					String[] fields = sort.getFields().split(",");
//					String[] orders = sort.getOrders().split(",");
//					for (int i = 0; i < fields.length - 1; i++) {
//						sql.append(dto.getFields().get(fields[i])).append(' ').append(orders[i]).append(',');
//					}
//					sql.append(dto.getFields().get(fields[fields.length - 1])).append(' ')
//							.append(orders[orders.length - 1]);
//				}
//				if (isDefaultSort && !isSort) {
//					sql.append(" order by UPDATE_TIME desc ");
//				}
//				sql.append(" limit ").append(page.getOffset()).append(",").append(page.getPageSize());
//				rs = this.queryset(sql.toString(), params);
//				List result = new ArrayList();
//				while (rs.next()) {
//					result.add(EntityTableReflectUtil.getObject(t.getClass(), rs));
//				}
//				page.setResult(result);
//			}
//		} catch (Exception e) {
//			LOG.error("分页查询出现了异常,查询语句：" + sql.toString(), e);
//		}
//	}

	/**
	 * @description mysql版本 通过sql语句进行分页查询
	 * @author fengya
	 * @date 2017年6月27日 下午1:58:49
	 * @param clazz
	 *            查询的结果对象类型
	 * @param sqlContext
	 *            查询的sql语句
	 * @param page
	 *            分页对象
	 * @param parameters
	 *            查询参数
	 * @return void
	 */
	public <E> void findPageBySql(Class<E> clazz, final String sqlContext, Page<E> page, final Object... parameters) {
		StringBuilder sql = new StringBuilder(sqlContext.toLowerCase());
		StringBuilder sqlCount = new StringBuilder();
		sqlCount.append(SQL_SELECT).append(" ").append(SQL_COUNT).append(" ")
				.append(sql.substring(sql.indexOf(SQL_FROM)));
		RowSet rs = this.queryset(sqlCount.toString(), parameters);
		try {
			if (rs.next()) {
				page.setTotalCount(rs.getInt(1));
				sql.append(" limit ").append(page.getOffset()).append(",").append(page.getPageSize());
				rs = this.queryset(sql.toString(), parameters);
				List<E> result = new ArrayList<E>();
				while (rs.next()) {
					result.add(EntityTableReflectUtil.getObject(clazz, rs));
				}
				page.setResult(result);
			}
		} catch (Exception e) {
			e.printStackTrace();
			LOG.error("分页查询出现了异常,查询语句：" + sqlContext, e);
		}
	}

	
//	/**
//	 * @description oracle版本，通过sql语句进行分页查询
//	 * @author fengya
//	 * @date 2017年6月27日 下午1:58:49
//	 * @param clazz
//	 *            查询的结果对象类型
//	 * @param sqlContext
//	 *            查询的sql语句
//	 * @param page
//	 *            分页对象
//	 * @param parameters
//	 *            查询参数
//	 * @return void
//	 */
//	public <E> void findPageBySql(Class<E> clazz, final String sqlContext, Page<E> page, final Object... parameters) {
//		StringBuilder sql = new StringBuilder(sqlContext.toLowerCase());
//		StringBuilder sqlCount = new StringBuilder();
//		sqlCount.append(SQL_SELECT).append(" ").append(SQL_COUNT).append(" countNum ")
//				.append(sql.substring(sql.indexOf(SQL_FROM)));
//		RowSet rs = this.queryset(sqlCount.toString(), parameters);
//		try {
//			if (rs.next()) {
//				page.setTotalCount(rs.getInt("countNum"));
//				StringBuilder sqlPage = new StringBuilder();
//				sqlPage.append("select * from (select t1.*,").append(ROWNUM_NAME).append(" ").append(ROWNUM_ALIAS).append(" from (").append(sql).append(") t1 ) t where t.rownum_<=").append(page.getOffset() + page.getPageSize()).append(" and t.rownum_>").append(page.getOffset());
//				rs = this.queryset(sqlPage.toString(), parameters);
//				List<E> result = new ArrayList<E>();
//				while (rs.next()) {
//					result.add(EntityTableReflectUtil.getObject(clazz, rs));
//				}
//				page.setResult(result);
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//			LOG.error("分页查询出现了异常,查询语句：" + sqlContext, e);
//		}
//	}
	/**
	 * @description 带有排序的分页sql查找
	 * @author fengya
	 * @date 2017年6月27日 下午2:10:22
	 * @param clazz
	 *            查询的结果对象类型
	 * @param sqlContext
	 *            查询的sql语句
	 * @param page
	 *            分页对象
	 * @param sort
	 *            排序字段对象
	 * @param isDefaultSort
	 *            是否支持默认排序，默认排序按照order by UPDATE_TIME desc进行
	 * @param parameters
	 *            查询参数
	 * @return void
	 */
	public <E> void findAsPageBySql(final Class<E> clazz, final String sqlContext, final Page<E> page, final Sort sort,
			boolean isDefaultSort, final Object... parameters) {
		StringBuilder sql = new StringBuilder(sqlContext.toLowerCase());
		StringBuilder sqlCount = new StringBuilder();
		sqlCount.append(SQL_SELECT).append(" ").append(SQL_COUNT).append(" ")
				.append(sql.substring(sql.indexOf(SQL_FROM)));
		RowSet rs = this.queryset(sqlCount.toString(), parameters);
		try {
			if (rs.next()) {
				page.setTotalCount(rs.getInt(1));
				boolean isSort = false;
				if (sort != null && !StringUtil.isNullOrEmpty(sort.getFields())) {
					isSort = true;
					sql.append(" order by ");
					String[] fields = sort.getFields().split(",");
					String[] orders = sort.getOrders().split(",");
					for (int i = 0; i < fields.length - 1; i++) {
						sql.append(EntityTableReflectUtil.classNameToTable(fields[i])).append(' ').append(orders[i])
								.append(',');
					}
					sql.append(EntityTableReflectUtil.classNameToTable(fields[fields.length - 1])).append(' ')
							.append(orders[fields.length - 1]);
				}
				if (isDefaultSort && !isSort) {
					sql.append(" order by UPDATE_TIME desc ");
				}
				sql.append(" limit ").append(page.getOffset()).append(",").append(page.getPageSize());
				rs = this.queryset(sql.toString(), parameters);
				List<E> result = new ArrayList<E>();
				while (rs.next()) {
					result.add(EntityTableReflectUtil.getObject(clazz, rs));
				}
				page.setResult(result);
			}
		} catch (Exception e) {
			e.printStackTrace();
			LOG.error("分页查询出现了异常,查询语句：" + sqlContext, e);
		}
	}

}
